<?php

class LightPressOptions {
    
    var $_descriptions = array(
        'basedir'           => array('the folder where your LightPress files live', ''),
        'url'               => array('your LightPress entry URL', 'Blog Configuration'),
        'wp_url'            => array('your WordPress entry URL', 'Blog Configuration'), // find a way to sync this
        'blogname'          => array('your blog name', 'Blog Configuration'),
        'shortname'         => array('a short name which identifies your blog, only letters and numbers allowed', 'Blog Configuration'),
        'description'       => array("your blog's description", 'Blog Configuration'),
        'copyright_notice'  => array("your blog's copyright notice", 'Blog Configuration'),
        'posts_per_page'    => array('number of posts to show in home/archive/category pages', 'Blog Configuration'),
        'posts_per_rss'     => array('number of posts to show in feeds', 'Blog Configuration'),
        'rss_use_excerpt'   => array('show a link to the post instead of the extra content in feeds', 'Blog Configuration'),
        'lang'              => array("ISO language of your blog/template, eg 'en_US'", 'Blog Configuration'),
        'template'          => array("name of your blog's template, eg. 'kubrick'", 'Blog Configuration'),
        'approx_sql_tstamp' => array("round off the current date by this number so that MySQL can cache queries", 'Blog Configuration'),
        'date_format'       => array("strftime() format to use for dates, eg '%A %d %B %Y'", 'Presentation'),
        'short_date_format' => array("strftime() abbreviated format to use for dates, eg '%d %b %Y'", 'Presentation'),
        'time_format'       => array("strftime() format to use for times, eg '%H:%M:%S'.  You can add your timezone by including 'CET', for example.", 'Presentation'),
        'short_time_format' => array("strftime() format to use for times, eg '%H:%M'", 'Presentation'),
        'archive_label'     => array("strftime() format to use for archive labels, eg '%B %Y'", 'Presentation'),
        'charset'           => array("character set of your blog/template, eg 'ISO-8859-1'", ''),
        'mail_mailer'       => array("leave empty or set to '0' (the number zero) to use PHP's mail() function, set to 'qmail' to use qmail", 'Mail Settings'),
        'mail_from'         => array('email address to use for generated mails', 'Mail Settings'),
        'mail_on_comment'   => array("leave empty or set to '0' (the number zero) if you do not want to receive mails for comment submission, set to '1' otherwise", 'Mail Settings'),
        'allowed_tags'      => array("list of allowed tags in comments/trackbacks, eg '<a> <acronym> <p> <br> <b> <blockquote> <code> <em> <i> <strike> <strong>'", 'Blog Configuration'),
        'post_prefix'       => array("URL prefix to use for posts", 'Permalinks'),
        'category_prefix'   => array("URL prefix for categories", 'Permalinks'),
        'archives_prefix'   => array("URL prefix for archives", 'Permalinks'),
        'pages_prefix'      => array("URL prefix for pages, leave empty to use automatic hierarchical URLs like /parent/subparent/child", 'Permalinks'),
        'pages_suffix'      => array("URL suffix for pages, eh .html", 'Permalinks'),
        'search_prefix'     => array("URL prefix for search pages", 'Permalinks'),
        'author_prefix'     => array("URL prefix for author pages", 'Permalinks'),
        'tag_prefix'        => array("URL prefix for tag search results", 'Permalinks'),
        'comments_prefix'   => array("URL prefix for paged comments", 'Permalinks'),
        'category_separator'=> array('character(s) used to separate category names', 'Presentation'),
        'comment_spam_kill' => array("leave empty or set to '0' (the number zero) to add supposed spam comments to the moderation queue, set to '1' to discard them", 'Mail Settings'),
        'comment_spam_mail' => array("leave empty or set to '0' (the number zero) if you not want to be notified when a comment is recognized as spam, set to '1' to receive a notification email", 'Mail Settings'),
        );

    var $_wpoption = array(
            'url' => 'home',
            'wp_url' => 'siteurl',
            'blogname' => 'blogname',
            'description'=> 'blogdescription',
            'posts_per_page' => 'posts_per_page',
            'posts_per_rss' => 'posts_per_rss',
            'charset' => 'blog_charset',
            'mail_from' => 'admin_email',
            'category_prefix' => 'category_base',
            'mail_on_comment'=>'comments_notify',
            'comment_spam_mail'=>'moderation_notify'
        );
    
    var $first_time = true;
    var $upgrading = false;
    var $htaccess_changed = false;
    var $critical;
    var $base;
    var $plugins;
    
    var $basedir;
    var $install_type = null;
    var $lp_Version = null;
    
    var $categories = array();
    var $hidden = array();
    
    function LightPressOptions($basedir = null) {
        // check for base dir setting
        if (is_null($basedir))
            $basedir = $this->getBaseDir();
        
        if (!is_null($basedir)) {
            $this->basedir = $basedir;
            require_once "$basedir/classes/Frontend.php";
            $this->critical = Frontend::getCriticalOptions();
            $this->base = Frontend::getBaseOptions();
            $this->plugins = Frontend::getDefaultPlugins();
            
            // set installation type
            $this->install_type = $this->getOption('install_type');
            
            // check version / upgrade
            $this->lp_version = $this->getVersion();
            
            // setup default plugins on first run
            if ($this->first_time) {
                $this->updateOption("lp_opt_plugins", $this->plugins);
            }
            // setup the list of plugin names
            if ($this->first_time || $this->upgrading) {
                $plugin_names = $this->getPluginList();
                foreach ($plugin_names as $k=>$v)
                    $plugin_names[$k] = 'PLUGIN_' . strtoupper(substr($v, 0, -4));
                $this->updateOption("lp_opt_plugin_names", $plugin_names);
            }
            
            // sort out options in categories, etc.
            $missing = array();
            foreach (array_merge($this->critical, array_keys($this->base)) as $k)
                $missing[$k] = '';
            unset($missing['plugins']);
            foreach ($this->_descriptions as $opt=>$attrs) {
                unset($missing[$opt]);
                list($desc, $cat) = $attrs;
                if (empty($cat)) {
                    $this->hidden[] = $opt;
                } else {
                    if (!isset($this->categories[$cat]))
                        $this->categories[$cat] = array();
                    $this->categories[$cat][] = $opt;
                }
            }
            if (count($missing) > 0)
                $this->categories['Beta Test Options'] = $missing;

            // augment descriptions for certain fields
            $permalink_verbs = Frontend::getPermalinkVerbs();
            foreach (array('post', 'archives', 'category') as $f) {
                if (isset($permalink_verbs[$f]))
                    $this->_descriptions["${f}_prefix"][0] .= '. Allowed verbs: {' . implode('}, {', array_keys($permalink_verbs[$f])) . '}.';
            }
            
        }
        
    }
    
    function check_option($opt) {
        
    }
    
    function getBaseDir() {
        
        if (($wp_opt = get_option('lp_opt_basedir')))
            $this->first_time = false;
        
        if ($basedir = trim($this->getPost('basedir'))) {
           if (@is_readable("$basedir/classes/Frontend.php"))
                return $basedir;
        }
        
        if ($wp_opt && @is_readable("$wp_opt/classes/Frontend.php"))
            return $wp_opt;
        
        // do not guess
        /*
        $basedir = dirname(dirname(dirname(dirname(__FILE__))));
        if (@is_readable("$basedir/classes/Frontend.php"))
            return $basedir;

        // try one more level down in case WP is in it's own directory
        $basedir = dirname(dirname(dirname(dirname(dirname(__FILE__)))));   
        if (@is_readable("$basedir/classes/Frontend.php"))
            return $basedir;
        
        */
    }
    
    function setInstallType() {
        // set installation type & check if it has changed
        $install_type = $this->getOption('install_type');
        
        if ($install_type != get_option('lp_opt_install_type')) {
            // update value
            $this->updateOption('lp_opt_install_type', $install_type);
            if ($install_type == 'root') {
                // fix URL in case the user forgets to set it to the root URL
                $this->updateOption('lp_opt_url', $this->getDefault('url'));
            } else {
                // fix URL if it's the same as the WP URL
                if (get_option('lp_opt_url') == get_option('home'))
                    $this->updateOption('lp_opt_url', $this->getDefault('url') . '/lightpress');
            }
            // update .htaccess
            $this->updateRewriteRules($install_type);
        }
        
        return $install_type;
    }
    
    function getVersion() {
        if (get_option('lp_opt_version') != Frontend::getVersion()) {
            $this->upgrading = true;
            $this->updateOption('lp_opt_version', Frontend::getVersion());
        }
    }
    
    function getPost($opt) {
        if (!isset($_POST["lp_opt_$opt"]))
            return null;
        else    // ugh, WP always adds slashes to everything
            return stripslashes($_POST["lp_opt_$opt"]);
    }
    
    function getDefault($opt) {
    
        $value = null;
        
        switch ($opt) {
            case 'basedir':
                $value = $this->basedir;
                break;
            case 'url':
                if (!$this->getOption('url') && $this->getOption('install_type') == 'testing')
                    $value = get_option('home') . '/' . $this->getOption('testing_dir');
                else
                    $value = get_option('home');
                break;
            case 'wp_url':          // fall through
            case 'blogname':        // fall through
            case 'description':     // fall through
            case 'posts_per_page':  // fall through
            case 'posts_per_rss':   // fall through
            case 'mail_from':       // fall through
            case 'mail_on_comment':       // fall through
                $value = get_option($this->_wpoption[$opt]);
                break;
            case 'rss_use_excerpt':
                $value = null; get_option('rss_use_excerpt');
                break;
            case 'shortname':
                $value = sanitize_title(get_option($this->_wpoption['blogname']), 'shortname');
                break;
            case 'charset':
                $value = strtoupper(get_option($this->_wpoption[$opt]));
                break;
            case 'post_prefix':
                $value = get_option('permalink_structure');
                // we keep an empty value, as it's the switch to use raw URLs
                if (!empty($value)) {
                    $value = preg_replace('/%([^%]+)%/', '{$1}', $value);
                    $value = $this->removeWPslashes($value);
                }
                break;
            case 'category_prefix':
                $value = get_option('category_base');
                // an empty value falls back to the default, which sets the same behaviour as WP
                if (empty($value) && get_option('permalink_structure'))
                    $value = $this->base[$opt];
                else
                    $value = $this->removeWPslashes($value);
                break;
            case 'archives_prefix':
                $value = get_option('permalink_structure');
                // if we have an empty value we are using raw URLs, and this option is useless
                if (!empty($value)) {
                    // use post prefix as our base, minus post-specific values
                    $links = array(explode('%postname%', $value),
                                   explode('%post_name%', $value),
                                   explode('%post_id%', $value));
                    $shortest = strlen($value);
                    foreach($links as $l)
                        $shortest = min($shortest, strlen($l[0]));
                        
                    $value = preg_replace('/%([^%]+)%/', '{$1}', substr($value, 0, $shortest));
                    $value = $this->removeWPslashes($value);
                    
                    // append year & month if they are missing
                    if (strpos($value, '{year}') === false)
                        $value .= '/{year}';
                    if (strpos($value, '{monthnum}') === false)
                        $value .= '/{monthnum}';
                }
                break;
            default:
                if (isset($this->base[$opt]))
                    $value = $this->base[$opt];
                break;
        }

        return $value;
    }
    
    function removeWPslashes($permalink) {
        // remove trailing & leading slashes inserted by WP
        if (substr($permalink, 0, 1) == '/')
            $permalink = substr($permalink, 1);
        if (substr($permalink, -1) == '/')
            $permalink = substr($permalink, 0, -1);
        return $permalink;
    }
    
    function updateOption($option_name, $newvalue) {
        // fix the broken WP update_option function (can't insert an empty value)
        global $wpdb, $cache_settings;
        if ( is_array($newvalue) || is_object($newvalue) )
            $newvalue = serialize($newvalue);
        
        $newvalue = trim($newvalue); // I can't think of any situation we wouldn't want to trim
        
        switch ($option_name) {
            case 'lp_opt_post_prefix':
                // parse post_prefix into something usable from Frontend
                $this->updateOption(
                    'lp_opt_post_permalink_struct',
                    Frontend::prefixToPermalinkStruct($newvalue));
                /*
                // sync with WP option
                if ($this->install_type == 'root') {
                    if (empty($newvalue))
                        $this->updateOption('permalink_structure', '');
                    else
                        $this->updateOption('permalink_structure', '/' . preg_replace('/{([^}]+)}/', '%$1%', str_replace('{post_name}', '{postname}', $newvalue)) . '/');
                }
                */
                break;
            case 'lp_opt_archives_prefix':
                // parse archives_prefix into something usable from Frontend
                $this->updateOption(
                    'lp_opt_archives_permalink_struct',
                    Frontend::prefixToPermalinkStruct($newvalue, 'archives'));
                break;
            case 'lp_opt_category_prefix':
                /*
                // sync with WP option
                if ($this->install_type == 'root') {
                    if (empty($newvalue))
                        $this->updateOption('category_base', '');
                    else
                        $this->updateOption('category_base', "/$newvalue");
                }
                */
                break;
            default:
                /*
                // sync with WP option, not necessary as now it works the other way around
                if ($this->install_type == 'root' && substr($option_name, 0, 7) == 'lp_opt_') {
                    $wpopt = substr($option_name, 7);
                    if (isset($this->_wpoption[$wpopt]))
                        $this->updateOption($this->_wpoption[$wpopt], $newvalue);
                }
                */
                break;
        }
        
        $newvalue = $wpdb->escape($newvalue);
        if (!$wpdb->get_var("SELECT option_name FROM $wpdb->options WHERE option_name = '$option_name'"))
            $wpdb->query("INSERT INTO $wpdb->options (option_name, option_value, autoload) VALUES ('$option_name', '$newvalue', 'yes')");
        else
            $wpdb->query("UPDATE $wpdb->options SET option_value = '$newvalue', autoload='yes' WHERE option_name = '$option_name'");
        
        wp_cache_delete($option_name, 'options');
        // Re cache settings
        $cache_settings = get_alloptions();
        return true;
    }
    
    function getOption($opt, $use_post=true) {
        if ($use_post) {
            if ($value = $this->getPost($opt))
                return $value;
        }
        $value = get_option("lp_opt_$opt");
        if (!empty($value))
            return $value;
        return $this->getDefault($opt);
    }
    
    function install() {
        foreach ($this->critical as $k) {
            $this->updateOption("lp_opt_$k", $this->getDefault($k));
        }
        foreach ($this->base as $k => $value) {
            if ($k == 'plugins')
                continue;
            $this->updateOption("lp_opt_$k", $this->getDefault($k));
        }
    }

    function updateRewriteRules($install_type='') {
        if (get_option('lp_opt_post_prefix')) {
            // spare users from sloppy code
            $old_error_level = error_reporting();
            error_reporting($old_error_level ^ E_NOTICE);
            
            save_mod_rewrite_rules();
            
            error_reporting($old_error_level);
            
            $this->htaccess_changed = false;
            
            // double check as WP does not return anything
            global $wp_rewrite;
            if (!$wp_rewrite->using_mod_rewrite_permalinks())
                return;
            
            $home_path = get_home_path();
            if (!file_exists("$home_path.htaccess") || !is_writable("$home_path.htaccess"))
                return;
            
            if ($install_type == 'testing') {
                $this->htaccess_changed = 'WP';
            } else {
                $this->htaccess_changed = 'LP';
                return true;
            }
        }
    }
    
    function getConfig($with_cache=false) {
        global $table_prefix;
        $config = '<?php
/*******************************************************************************
 * LightPress - http://lightpress.org
 *
 * Copyright 2004-2005 Ludovico Magnocavallo, Jerome Lavigne
 * Released under the GPL http://www.gnu.org/copyleft/gpl.html
 *
 * $Id: LightPressOptions.php,v 1.41 2005/07/21 16:27:49 ludo Exp $
 ******************************************************************************/


// database configuration

$db_options = array(
    \'user\'              => \'' . DB_USER . '\',
    \'passwd\'            => \'' . DB_PASSWORD . '\',
    \'db\'                => \'' . DB_NAME . '\',
    \'prefix\'            => \'' . substr($table_prefix, 0, -1) . '\',
    \'server\'            => \'' . DB_HOST . '\'
);

// end user configuration

$lp_path = \'' . get_option('lp_opt_basedir') . '\';

if (!is_dir($lp_path) || !is_readable($lp_path))
    die("invalid path $lp_path in " . __FILE__);

if (version_compare(PHP_VERSION, \'4.3.1\', \'<\'))
    define(\'PATH_SEPARATOR\', (DIRECTORY_SEPARATOR == \'/\' ? \':\' : \';\'));

ini_set(
    \'include_path\',
    ini_get(\'include_path\') . PATH_SEPARATOR . $lp_path);

// you can change these two values to troubleshoot errors
error_reporting(E_ALL ^ E_NOTICE);
ini_set(\'display_errors\', 0);

$cache = null;

' . ($with_cache ? '' : '// ') . 'include_once \'cache/init.php\';

require_once \'classes/Frontend.php\';

// there should be no spaces or empty lines after the PHP close tag below

?>';

        return $config;
    }
    
    function getPluginList() {
        
        if (is_null($this->basedir))
            return array();
        
        $plugins = array();
        $plugin_dir = $this->basedir . DIRECTORY_SEPARATOR . 'plugins';
    
        $d = opendir($plugin_dir);
        while (($plugin_file = readdir($d)) !== false) {
            if (!is_file($plugin_dir . DIRECTORY_SEPARATOR . $plugin_file) || substr($plugin_file, -4) != '.php')
                continue;
            $plugins[] = $plugin_file;
        }
        closedir($d);
        
        sort($plugins);
        
        return $plugins;
        
    }
    
}

?>
